/**
 * 复刻ES6 Promise
 * @param callback
 * @constructor
 */
function Promise(callback){
    //默认初始化为pending
    this.state=this.STATE_PENDING;

    //resolve或reject时需要改变状态并把对应的参数传入
    //若Promise是同步resolve或reject，则要等到下一轮事件循环再执行（因要等待then的回调函数赋值）
    //若Promise是异步resolve或reject，则可以直接执行
    //关于setTimeout是下一轮事件循环再执行（若能在本轮事件结束时执行最好）
    const resolve=(arg) => {
        this.thenResolve
            ?this.changeState(this.STATE_RESOLVED, arg)
            :setTimeout(() => {this.changeState(this.STATE_RESOLVED, arg);}, 0);
    };
    const reject=(arg) => {
        this.thenReject
            ?this.changeState(this.STATE_REJECTED, arg)
            :setTimeout(() => {this.changeState(this.STATE_REJECTED, arg);}, 0);
    };

    //马上执行
    callback(resolve, reject);
}

Promise.author='toffy';

/**
 * 静态变量
 */
Promise.prototype.STATE_PENDING='Pending';
Promise.prototype.STATE_RESOLVED='Resolved';
Promise.prototype.STATE_REJECTED='Rejected';

/**
 * promise状态改变事件
 * @param newState
 * @param arg
 */
Promise.prototype.changeState=function(newState, arg){
    this.state=newState;

    if(newState==this.STATE_RESOLVED) {
        //有设置下一个then并且有包含第一个参数(resolve)时才需要把值继续传下去
        if(typeof this.thenResolve == 'function') {
            var thenReturnValue=this.thenResolve(arg);
            //then里面的返回值，注意区分普通类型和Promise类型
            if(thenReturnValue instanceof Promise){
                //必须也要传nextPromiseReject，否则在then里return一个rejected promise将不会触发后面的catch方法
                thenReturnValue.then(this.nextPromiseResolve, this.nextPromiseReject);
            }else {
                //往后面一个then传值
                this.nextPromiseResolve(thenReturnValue);
            }
        }
    }else if(newState==this.STATE_REJECTED){
        var promise=this;
        //如果当前promise没有设置reject函数，则一直往后面每个promise中找，直到找到有reject回调函数的
        while (typeof promise.thenReject != 'function'&&promise.nextPromise){
            promise=promise.nextPromise;
        }

        if(typeof promise.thenReject == 'function') {
            //找到了最近一个包含reject函数的promise
            promise.thenReject(arg);
        }
        //如果最后还是没找到reject则不会有任何反应
    }
};

/**
 * then里面主要为了设置nextPromiseResolve等回调函数名
 * @param resolveFunc
 * @param rejectFunc
 * @returns {Promise}
 */
Promise.prototype.then=function(resolveFunc, rejectFunc){
    this.thenResolve = resolveFunc;
    this.thenReject = rejectFunc;

    //返回一个新的promise
    this.nextPromise=new Promise((resolve, reject) => {
        //结果处理函数往下传
        this.nextPromiseResolve=resolve;
        this.nextPromiseReject=reject;
    });

    return this.nextPromise;
};

/**
 * 用于捕获错误(reject)的回调函数
 * @param rejectFunc
 * @returns {Promise|Promise.<T>}
 */
Promise.prototype.catch=function(rejectFunc){
    return this.then(null, rejectFunc);
};

/**
 * 合并多个Promise实例，同时执行完后一起返回
 * @param promises
 * @returns {Promise}
 */
Promise.all=function(promises){
    return new Promise(function(resolve, reject){
        var resolveData=[]; //正常返回值数组，注意顺序要跟promise一一对应
        var resolveCount=0; //当前已经正常返回的个数，用于标识是否全部已正常返回
        var hasRejected=false;
        promises.forEach(function(promise, i){
            Promise.resolve(promise)
                .then(function(data){
                    resolveData[i]=data;
                    resolveCount++;

                    if(resolveCount==promises.length){
                        //此时resolveData里的每一项也应该填满了
                        resolve(resolveData); //返回一个正常结果数组
                    }
                })
                .catch(function(data){
                    //只要有一个被reject的话就直接reject，reject一次就够了
                    if(!hasRejected) {
                        reject(data); //返回一个异常结果
                        hasRejected=true;
                    }
                })
            ;
        });
    });
};

/**
 * 转换为Promise对象
 * @param obj
 * @returns {Promise}
 */
Promise.resolve=function(obj){
    if(!obj){
        //不带任何参数，直接返回一个Resolved状态的Promise对象
        return new Promise(resolve => {resolve()});
    }else {
        //Promise实例直接返回
        if (obj instanceof Promise) {
            return obj;
        }else if(typeof obj.then == 'function'){
            //参数是一个thenable对象（含方法then(resolve, reject)）
            return new Promise(obj.then);
        }else{
            //如果是其他情况则直接返回该参数
            return new Promise(resolve => {resolve(obj)});
        }
    }
};

/**
 * 转换为Promise对象
 * @param obj
 * @returns {Promise}
 */
Promise.reject=function(obj){
    if(!obj){
        //不带任何参数，直接返回一个Rejected状态的Promise对象
        return new Promise((resolve, reject) => {reject()});
    }else {
        //Promise实例直接返回
        if (obj instanceof Promise) {
            return obj;
        }else if(typeof obj.then == 'function'){
            //参数是一个thenable对象（含方法then(resolve, reject)）
            return new Promise(obj.then);
        }else{
            //如果是其他情况则直接返回该参数
            return new Promise((resolve, reject) => {reject(obj)});
        }
    }
};

//module.exports=Promise;
export default Promise